home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
gnu
/
gas
/
gassrc02.zoo
/
ns32k.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-24
|
51KB
|
1,769 lines
/* ns32k.c -- Assemble on the National Semiconductor 32k series
Copyright (C) 1987 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GAS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define NS32K
/*#define SHOW_NUM 1*/ /* uncomment for debugging */
#include <stdio.h>
#include <ctype.h>
#ifdef USG
#include <string.h>
#else
#include <strings.h>
#endif
#include "ns32k-opcode.h"
#include "as.h"
#include "obstack.h"
#include "frags.h"
#include "struc-symbol.h"
#include "flonum.h"
#include "expr.h"
#include "md.h"
#include "hash.h"
#include "write.h"
#include "symbols.h"
/* Macros */
#define IIF_ENTRIES 13 /* number of entries in iif */
#define PRIVATE_SIZE 256 /* size of my garbage memory */
#define MAX_ARGS 4
#define DEFAULT -1 /* addr_mode returns this value when plain constant or label is encountered */
#define IIF(ptr,a1,c1,e1,g1,i1,k1,m1,o1,q1,s1,u1) \
iif.iifP[ptr].type= a1; \
iif.iifP[ptr].size= c1; \
iif.iifP[ptr].object= e1; \
iif.iifP[ptr].object_adjust= g1; \
iif.iifP[ptr].pcrel= i1; \
iif.iifP[ptr].pcrel_adjust= k1; \
iif.iifP[ptr].im_disp= m1; \
iif.iifP[ptr].relax_substate= o1; \
iif.iifP[ptr].bit_fixP= q1; \
iif.iifP[ptr].addr_mode= s1; \
iif.iifP[ptr].bsr= u1;
#ifdef SEQUENT_COMPATABILITY
#define LINE_COMMENT_CHARS "|"
#define ABSOLUTE_PREFIX '@'
#define IMMEDIATE_PREFIX '#'
#endif
#ifndef LINE_COMMENT_CHARS
#define LINE_COMMENT_CHARS "#"
#endif
char comment_chars[] = "#";
char line_comment_chars[] = LINE_COMMENT_CHARS;
#if !defined(ABSOLUTE_PREFIX) && !defined(IMMEDIATE_PREFIX)
#define ABSOLUTE_PREFIX '@' /* One or the other MUST be defined */
#endif
struct addr_mode {
char mode; /* addressing mode of operand (0-31) */
char scaled_mode; /* mode combined with scaled mode */
char scaled_reg; /* register used in scaled+1 (1-8) */
char float_flag; /* set if R0..R7 was F0..F7 ie a floating-point-register */
char am_size; /* estimated max size of general addr-mode parts*/
char im_disp; /* if im_disp==1 we have a displacement */
char pcrel; /* 1 if pcrel, this is really redundant info */
char disp_suffix[2]; /* length of displacement(s), 0=undefined */
char *disp[2]; /* pointer(s) at displacement(s)
or immediates(s) (ascii) */
char index_byte; /* index byte */
};
typedef struct addr_mode addr_modeS;
char *freeptr,*freeptr_static; /* points at some number of free bytes */
struct hash_control *inst_hash_handle;
struct ns32k_opcode *desc; /* pointer at description of instruction */
addr_modeS addr_modeP;
char EXP_CHARS[] = "eE";
char FLT_CHARS[] = "fd"; /* we don't want to support lowercase, do we */
long omagic = OMAGIC;
void md_number_to_disp();
void md_number_to_imm();
segT evaluate_expr();
void fix_new_ns32k();
/* UPPERCASE denotes live names
* when an instruction is built, IIF is used as an intermidiate form to store
* the actual parts of the instruction. A ns32k machine instruction can
* be divided into a couple of sub PARTs. When an instruction is assembled
* the appropriate PART get an assignment. When an IIF has been completed it's
* converted to a FRAGment as specified in AS.H */
/* internal structs */
struct option {
char *pattern;
unsigned long or;
unsigned long and;
};
typedef struct {
int type; /* how to interpret object */
int size; /* Estimated max size of object */
unsigned long object; /* binary data */
int object_adjust; /* number added to object */
int pcrel; /* True if object is pcrel */
int pcrel_adjust; /* It's value reflects the length in bytes from the instruction start to the displacement */
int im_disp; /* True if the object is a displacement */
relax_substateT relax_substate; /* Initial relaxsubstate */
bit_fixS *bit_fixP; /* Pointer at bit_fix struct */
int addr_mode; /* What addrmode do we associate with this iif-entry */
char bsr; /* Sequent hack */
}iif_entryT; /* Internal Instruction Format */
struct int_ins_form {
int instr_size; /* Max size of instruction in bytes. */
iif_entryT iifP[IIF_ENTRIES+1];
};
struct int_ins_form iif;
expressionS exprP;
char *input_line_pointer;
/* description of the PARTs in IIF
*object[n]:
* 0 total length in bytes of entries in iif
* 1 opcode
* 2 index_byte_a
* 3 index_byte_b
* 4 disp_a_1
* 5 disp_a_2
* 6 disp_b_1
* 7 disp_b_2
* 8 imm_a
* 9 imm_b
* 10 implied1
* 11 implied2
*
* For every entry there is a datalength in bytes. This is stored in size[n].
* 0, the objectlength is not explicitly given by the instruction
* and the operand is undefined. This is a case for relaxation.
* Reserve 4 bytes for the final object.
*
* 1, the entry contains one byte
* 2, the entry contains two bytes
* 3, the entry contains three bytes
* 4, the entry contains four bytes
* etc
*
* Furthermore, every entry has a data type identifier in type[n].
*
* 0, the entry is void, ignore it.
* 1, the entry is a binary number.
* 2, the entry is a pointer at an expression.
* Where expression may be as simple as a single '1',
* and as complicated as foo-bar+12,
* foo and bar may be undefined but suffixed by :{b|w|d} to
* control the length of the object.
*
* 3, the entry is a pointer at a bignum struct
*
*
* The low-order-byte coresponds to low physical memory.
* Obviously a FRAGment must be created for each valid disp in PART whose
* datalength is undefined (to bad) .
* The case where just the expression is undefined is less severe and is
* handled by fix. Here the number of bytes in the objectfile is known.
* With this representation we simplify the assembly and separates the
* machine dependent/independent parts in a more clean way (said OE)
*/
struct option opt1[]= /* restore, exit */
{
{ "r0", 0x80, 0xff },
{ "r1", 0x40, 0xff },
{ "r2", 0x20, 0xff },
{ "r3", 0x10, 0xff },
{ "r4", 0x08, 0xff },
{ "r5", 0x04, 0xff },
{ "r6", 0x02, 0xff },
{ "r7", 0x01, 0xff },
{ 0 , 0x00, 0xff }
};
struct option opt2[]= /* save, enter */
{
{ "r0", 0x01, 0xff },
{ "r1", 0x02, 0xff },
{ "r2", 0x04, 0xff },
{ "r3", 0x08, 0xff },
{ "r4", 0x10, 0xff },
{ "r5", 0x20, 0xff },
{ "r6", 0x40, 0xff },
{ "r7", 0x80, 0xff },
{ 0 , 0x00, 0xff }
};
struct option opt3[]= /* setcfg */
{
{ "c", 0x8, 0xff },
{ "m", 0x4, 0xff },
{ "f", 0x2, 0xff },
{ "i", 0x1, 0xff },
{ 0 , 0x0, 0xff }
};
struct option opt4[]= /* cinv */
{
{ "a", 0x4, 0xff },
{ "i", 0x2, 0xff },
{ "d", 0x1, 0xff },
{ 0 , 0x0, 0xff }
};
struct option opt5[]= /* string inst */
{
{ "b", 0x2, 0xff },
{ "u", 0xc, 0xff },
{ "w", 0x4, 0xff },
{ 0 , 0x0, 0xff }
};
struct option opt6[]= /* plain reg ext,cvtp etc */
{
{ "r0", 0x00, 0xff },
{ "r1", 0x01, 0xff },
{ "r2", 0x02, 0xff },
{ "r3", 0x03, 0xff },
{ "r4", 0x04, 0xff },
{ "r5", 0x05, 0xff },
{ "r6", 0x06, 0xff },
{ "r7", 0x07, 0xff },
{ 0 , 0x00, 0xff }
};
#if !defined(NS32032) && !defined(NS32532)
#define NS32032
#endif
struct option cpureg_532[]= /* lpr spr */
{
{ "us", 0x0, 0xff },
{ "dcr", 0x1, 0xff },
{ "bpc", 0x2, 0xff },
{ "dsr", 0x3, 0xff },
{ "car", 0x4, 0xff },
{ "fp", 0x8, 0xff },
{ "sp", 0x9, 0xff },
{ "sb", 0xa, 0xff },
{ "usp", 0xb, 0xff },
{ "cfg", 0xc, 0xff },
{ "psr", 0xd, 0xff },
{ "intbase", 0xe, 0xff },
{ "mod", 0xf, 0xff },
{ 0 , 0x00, 0xff }
};
struct option mmureg_532[]= /* lmr smr */
{
{ "mcr", 0x9, 0xff },
{ "msr", 0xa, 0xff },
{ "tear", 0xb, 0xff },
{ "ptb0", 0xc, 0xff },
{ "ptb1", 0xd, 0xff },
{ "ivar0", 0xe, 0xff },
{ "ivar1"